# encoding=utf8
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

import json
import time
import re
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
import pytesseract  # 使用tesseract识别时包
from PIL import Image, ImageEnhance
from selenium import webdriver
from selenium.webdriver.common.by import By
from start.Ten_OCR import ocr_ten

import base64
import hashlib
#import time
import random
import string
from urllib.parse import quote
import requests

def curlmd5(src):#md5
    m = hashlib.md5(src.encode('UTF-8'))
    return m.hexdigest().upper()

# 请求时间戳（秒级），用于防止请求重放（保证签名5分钟有效）
def get_params(base64_data):#接口函数
    t = time.time()
    time_stamp=str(int(t))
    # 请求随机字符串，用于保证签名不可预测
    nonce_str = ''.join(random.sample(string.ascii_letters + string.digits, 10))
    # 应用标志，这里修改成自己的id和key
    app_id = '2108132630'
    app_key = 'aW4D8RnOBvHs9XE8'
    # app_id = '2108079980'
    # app_key = '5oMzaxluT7pu5zS0'
    params = {'app_id':app_id,
              'image':base64_data,
              'time_stamp':time_stamp,
              'nonce_str':nonce_str,
              }
    sign_before = ''
    # 要对key排序再拼接
    for key in sorted(params):
        # 键值拼接过程value部分需要URL编码，URL编码算法用大写字母，例如%E8。quote默认大写。
        sign_before += '{}={}&'.format(key,quote(params[key], safe=''))
    # 将应用密钥以app_key为键名，拼接到字符串sign_before末尾
    sign_before += 'app_key={}'.format(app_key)
    # 对字符串sign_before进行MD5运算，得到接口请求签名
    sign = curlmd5(sign_before)
    params['sign'] = sign
    return params

def ocr_ten(filename):
    url = "https://api.ai.qq.com/fcgi-bin/ocr/ocr_generalocr"# 通用
    #url = "https://api.ai.qq.com/fcgi-bin/ocr/ocr_handwritingocr" # 手写体
    with open(filename,'rb') as fin:
        image_data = fin.read()
    base64_data = base64.b64encode(image_data)
    params = get_params(base64_data)
    r = requests.post(url,data=params)
    print("-----------------------------post请求----------------------------------")
    print(r)
    print("-----------------------------接口输出-------------------01--------------")
    item_list = r.json()['data']['item_list']
    print(item_list)
    print("-----------------------------接口输出-------------------02--------------")
    for s in item_list:
        print(s['itemstring'])
        yzm = s['itemstring']
    return yzm
    print("-----------------------------输出结束-----------------------------------")

# 开启后台模式
def OpenChrome():
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_argument('--headless')
    driver = webdriver.Chrome(chrome_options=chrome_options)
    return driver

# 前台开启浏览器模式
def openChrome():
    # 加启动配置
    option = webdriver.ChromeOptions()
    #option = webdriver.FirefoxOptions()
    option.add_argument('disable-infobars')
    # 打开chrome浏览器
    driver = webdriver.Chrome(chrome_options=option)
    #driver = webdriver.Firefox(firefox_options=option)
    driver.maximize_window()#最大化浏览器
    return driver

def extract():#验证码截图 + 识别
    location = driver.find_element_by_id('icode').location # 根据验证码图片ID实现自动定位
    size = driver.find_element_by_id('icode').size
    left = location['x']
    top =  location['y']
    right = location['x'] + size['width']
    bottom = location['y'] + size['height']
    driver.save_screenshot("./01.png")
    # 372151181101305
    ran = Image.open("./01.png")
    #box = (705, 342, 904, 442)  # 获取验证码位置,就使用了手动定位，代表（左，上，右，下）
    box = (left, top, right, bottom)
    ran.crop(box).save("./02.png")

    # 4、获取验证码图片，读取验证码
    imageCode = Image.open("./02.png") # 图像增强，二值化
    # imageCode.load()
    sharp_img = ImageEnhance.Contrast(imageCode).enhance(3.0)
    sharp_img.save("./03.png")
    sharp_img.load()  # 对比度增强
    time.sleep(2)# 缓冲
    # 5、收到验证码，进行输入验证
    # code = pytesseract.image_to_string(sharp_img).strip()
    # print(code)
    yzm = remove_punctuation(ocr_ten('02.png'))
    elem = driver.find_element_by_id("txtSecretCode")
    elem.clear()
    elem.send_keys(yzm)
    driver.find_element_by_xpath("//*[@name='Button1']").click()# 登陆

def remove_punctuation(line):
    line=''.join(re.findall(u'[a-zA-Z0-9]+', line))
    # rule = re.compile(ur"[^a-zA-Z0-9\u4e00-\u9fa5]")
    # line = rule.sub('',line)
    """在前面加”ur“，u的意思是表明后面有Unicode字符，
    汉字的范围为”\u4e00-\u9fa5“，
    这个是用Unicode表示的，所以前面必须要加”u“；
    字符”r“的意思是表示忽略后面的转义字符，
    这样简化了后面正则表达式里每遇到一个转义字符还得挨个转义的麻烦"""
    return line

def F_grade(c_number, name):
    url = "http://218.56.144.61/default2.aspx"
    #url = "http://218.56.144.42/default2.aspx" # 备用
    # 获取考号情况再另一个函数
    driver.get(url)
    elem = driver.find_element_by_id("txtUserName")
    elem.clear()
    elem.send_keys(c_number)
    elem = driver.find_element_by_id("TextBox2")
    elem.clear()
    elem.send_keys(name)
    #driver.find_element_by_xpath("//*[@name='yzm']").click()# 点击获取验证码，正方不需要
    # time.sleep(1) # 给验证码流出缓冲时间
    # driver.find_element_by_xpath("//*[@id='stu_reg_vcode']").click()# 点击刷新验证码
    #----------------------此处存放验证码截图 / 识别函数------------------------#
    #time.sleep(1) # 给验证码流出缓冲时间
    extract()
    #---------------------------------------------------------------------------#

# 除知道完整考号的情况下，直接调用查询
# 否则不获取姓名
def C_number():
    return F_grade(201643010119, '547feng')#测试

    c_number = str(input("输入完整考号："))
    name = input("输入姓名：")


# 授权操作
def operationAuth(driver):
    url = "https://www.chsi.com.cn/cet/"
    id = ["zkzh", "xm"]
    # 获取考号情况再另一个函数
    driver.get(url)
    for pwd in id:
        elem = driver.find_element_by_id(pwd)
        elem.clear()
        elem.send_keys()

    content = driver.page_source.encode('utf-8')  # 获取提交后的页面数据（列表中的）
    l1 = str(content, encoding="utf-8")  # 字符转换
    # str4 = "".join(hrl)#列表转字符串
    tt = re.findall(r'(?<=<td>).*?(?=</td>)', l1)  # 提取列表中的td部分
    tt = tt[3:]  # 再提取后面有数据的部分
    b = [tt[i:i + 3] for i in range(0, len(tt), 3)]  # 三个一组重新形成列表
    con = len(b)  # 记录三个一组有几组（小列表）
    url = {'id', 'name', 'age'}  # 构建空字典
    i = 0
    jsObj = []  # 构建空列表
    while i < con:
        b = dict(zip(url, tt[i]))  # 循环合并字典
        jsObj.append(b)
        i += 1
    json_str2 = json.dumps(jsObj)  # 字典转json
    fileObject = open('jsonFile.json', 'w')
    fileObject.write(json_str2)
    fileObject.close()
    print("-----------------------------------------------------------------------------------------------------------")
    print("python原始数据：", repr(jsObj))
    print("json对象：", json_str2)
    print("-----------------------------------------------------------------------------------------------------------")


# 方法主入口
if __name__ == '__main__':
    # 加启动配置
    driver = openChrome()
    C_number()
    # 弹窗判断是否存在
    while 1:
        result = EC.alert_is_present()(driver)
        if result:
            if result.text == '验证码不正确！！' or result.text == '密码错误！！':
                print(result.text)
                result.accept()# 点击取消为dismiss()
                C_number()
        else:
            print("alert 未弹出！")
            break
    #content = driver.page_source.encode('utf-8')  # 获取提交后的页面数据（列表中的）
    #operationAuth(driver)
    driver.close() #关闭,
